package util;

import com.alibaba.fastjson.JSON;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

import java.util.*;
import java.util.stream.Collectors;

/**
 * java 1.8 常用写法
 */
public class Stream_ {

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode(of = {"id"})
    public static class VO {
        private Integer id;
        private String name;
        private Integer sum;
    }

    public static class Tuple<A, B> {
        private static final Tuple empty = new Tuple();
        private A first;
        private B second;

        private Tuple() {
        }

        public static <A, B> Tuple<A, B> empty() {
            return empty;
        }

        public static <A, B> Tuple<A, B> of(A first, B second) {
            Tuple<A, B> tuple = new Tuple();
            tuple.setFirst(first);
            tuple.setSecond(second);
            return tuple;
        }

        public A getFirst() {
            return this.first;
        }

        public void setFirst(A first) {
            this.first = first;
        }

        public B getSecond() {
            return this.second;
        }

        public void setSecond(B second) {
            this.second = second;
        }
    }


    public static List<VO> list = new ArrayList<>();

    static {
        list.add(new VO(1, "第1.1", 1));
        list.add(new VO(1, "第1.1", 2));
        list.add(new VO(1, "第1.2", 1));
        list.add(new VO(2, "第3", 2));
        list.add(new VO(4, "第4", 1));
    }

    public static void main(String[] args) {
//        collect();
//        map();
//        repeat();
//        nullOf();
        sort();
//        sum();
    }


    /**
     * collect 操作
     */
    public static void collect() {
        list.stream().forEach(a->a.setName("111111"));
        list.stream().filter(a -> a.getId() != null).collect(Collectors.toList());
        Set<VO> set = list.stream().filter(a -> a.getId() != null).collect(Collectors.toSet());
        System.out.println(JSON.toJSONString(set));

        //key不允许重复
//        Map<Integer, VO> voMap = list.stream().collect(Collectors.toMap(VO::getId, a -> a));
//        System.out.println(JSON.toJSONString(voMap));

        //key允许重复 v是基础类型
        Map<Integer, Integer> map = list.stream().collect(Collectors.toMap(VO::getId, VO::getId, (oldValue, newValue) -> newValue));
        System.out.println(JSON.toJSONString(map));

        //key允许重复 v是对象
        Map<Integer, VO> map2 = list.stream().collect(Collectors.toMap(VO::getId, a -> a, (oldValue, newValue) -> newValue));
        System.out.println(JSON.toJSONString(map2));

        Map<Integer, List<VO>> mapList = list.stream().collect(Collectors.groupingBy(VO::getId));
        System.out.println(JSON.toJSONString(mapList));

        Map<Integer, Set<VO>> collect = list.stream().collect(Collectors.groupingBy(vo -> vo.getId(), Collectors.toSet()));
        System.out.println(JSON.toJSONString(collect));

        //collectingAndThen todo
    }

    /**
     * map操作
     * filter 操作必须要重新用返回值接受才可以 List<VO> 新的 = list.stream().filter(？).collect(Collectors.toList());
     * peek 必须用 集合处理，❤可以不用接收对象❤ 不需要对象接受 = list.stream().peek(?).collect(Collectors.toList());
     */
    public static void map() {

        List<Integer> idList = list.stream().map(VO::getId).collect(Collectors.toList());

        //peek函数是一种特殊的map函数，当函数没有返回值或者参数就是返回值的时候可以使用peek函数。
        //都会直接修改返回值
        List<VO> list3 = list.stream()
                .peek(a -> {
                    a.setName(a.getName() + "*");
                }).filter(a -> null != a.getId())
                .collect(Collectors.toList());
        System.out.println(JSON.toJSONString(list));
        System.out.println(JSON.toJSONString(list3));

        list.stream().map(a -> {
            a.setName(a.getName() + "*");
            return a;
        }).collect(Collectors.toList());
        System.out.println(JSON.toJSONString(list));

        List<String> words = Arrays.asList("hello", "word");
        List<List<String>> list1 = words.stream()
                .map(w -> Arrays.asList(w.split("")))    //[[h,e,l,l,o],[w,o,r,l,d]]
                .collect(Collectors.toList());
        System.out.println(JSON.toJSONString(list1));

        List<String> list2 = words.stream()
                .flatMap(w -> Arrays.stream(w.split("")))  // [h,e,l,l,o,w,o,r,l,d]
                .collect(Collectors.toList());
        System.out.println(list2);

    }


    //去重
    public static void repeat() {

        //去重复1
//        List<VO> distinct1 = list.stream().distinct().collect(Collectors.toList());
//
//
//        // 根据id去重
//        List<VO> list2 = list.stream().collect(Collectors.collectingAndThen(
//                Collectors.toCollection(
//                        () -> new TreeSet<>(Comparator.comparing(VO::getId))), ArrayList::new)
//        );
//        System.out.printf(JSON.toJSONString(list2));

        //多字段去重复
        List<VO> list3 = list
                .stream()
                .collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(
                        Comparator.comparing(x -> x.getId() + x.getName()))), ArrayList::new));
        System.out.printf(JSON.toJSONString(list3));
    }

    //排序

    public static void sort() {
        list.sort(Comparator.comparing(VO::getId));
        Collections.reverse(list);


//        list.sort(Comparator.comparing(VO::getSum).thenComparing(VO::getId));

        System.out.println(JSON.toJSONString(list));



    }

    //Null预处理

    public static void nullOf() {
        Object s1 = Optional.of(System.currentTimeMillis())
                .map(id -> {
                    return null;
                })
                .orElseGet(() -> {
                    return "111";
                });
        System.out.println(s1);


        Object s2 = Optional.ofNullable(null)
                .orElse("3");
        System.out.println(s2);
    }


    public static void sum() {

        //分组求和
        Map<Integer, LongSummaryStatistics> collect = list.stream()
                .collect(Collectors.groupingBy(VO::getId, Collectors.summarizingLong(VO::getSum)));

        List<Tuple<Integer, LongSummaryStatistics>> tupleList = collect.entrySet().stream().map(a -> Tuple.of(a.getKey(), a.getValue())).collect(Collectors.toList());

        tupleList.sort(Comparator.comparingLong(a -> a.getSecond().getSum()));
        Collections.reverse(tupleList);


        System.out.println(JSON.toJSONString(tupleList));

        //分组计数
        Map<Integer, Integer> mapList = list.stream()
                .collect(Collectors.groupingBy(VO::getId))
                .entrySet().stream()
                .collect(Collectors.toMap(a -> a.getKey(), b -> b.getValue().size(), (oldValue, newValue) -> newValue));
        System.out.println(mapList);



    }



}
